﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using Resolve.Contracts;
using Resolve.FlagInfo;
using Resolve.Web;

namespace Resolve.Core
{
    public class HtmlGeneraterFromString : IHtmlGenerater
    {
        /// <summary>
        /// 代码标志
        /// </summary>
        public FlagCodeInFile FlagCodeInFile { private get; set; }

        /// <summary>
        /// 字符读取对象
        /// </summary>
        private StringReader _stringReader;

        /// <summary>
        /// 初始化
        /// </summary>
        private void InitStream()
        {
            if (_stringReader != null)
            {
                _stringReader.Close();
            }
            _stringReader = new StringReader(FlagCodeInFile.Source);
        }

        /// <summary>
        /// 替换标志，生成Html代码
        /// </summary>
        /// <returns></returns>
        public string Generate()
        {
            InitStream();
            try
            {
                if (FlagCodeInFile == null || FlagCodeInFile.LsCode == null || FlagCodeInFile.LsCode.Count == 0)
                {
                    string str = _stringReader.ReadToEnd();
                    Dispose();
                    return str;
                }
                StringBuilder sbHtml = new StringBuilder();
                object compileObject = FlagCodeInFile.CompileObject;
                NoLayout(ref compileObject, sbHtml);
                Dispose();
                return sbHtml.ToString();
            }
            catch (Exception ex)
            {
                Dispose();
                throw new Exception(ex.Message);
            }
        }


        private void NoLayout(ref object compileObject, StringBuilder sbHtml)
        {
            Type compileType = null;
            if (compileObject != null)
            {
                compileType = FlagCodeInFile.CompileObject.GetType();
            }
            List<FlagCode> lsCode = FlagCodeInFile.LsCode;
            int iPosition = 0;
            for (int i = 0; i < lsCode.Count; i++)
            {
                char[] bTemp = new char[lsCode[i].Start - iPosition];
                if (bTemp.Length != 0)
                {
                    _stringReader.Read(bTemp, 0, bTemp.Length);
                    sbHtml.Append(bTemp);
                }
                string htmlCode = string.Empty;
                switch (lsCode[i].FlagStyle)
                {
                    case FlagStyle.Statement:
                    case FlagStyle.Using:
                    case FlagStyle.Comment:
                    case FlagStyle.Layout:
                        break;
                    case FlagStyle.Property:
                        {
                            if (compileType == null) continue;
                            MethodInfo m = compileType.GetMethod(ResolveConfig.PropertyCodeName + i);
                            Func<string> action = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), compileObject, m);
                            htmlCode = action();
                        }
                        break;
                    case FlagStyle.Func:
                        {
                            if (compileType == null) continue;
                            MethodInfo m = compileType.GetMethod(ResolveConfig.FuncCodeName + i);
                            Func<string> action = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), compileObject, m);
                            htmlCode = action();
                        }
                        break;
                    case FlagStyle.Body:
                        {
                            if (compileType == null) continue;
                            MethodInfo m = compileType.GetMethod(ResolveConfig.BodyCodeName + i);
                            Func<string> action = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), compileObject, m);
                            htmlCode = action();
                        }
                        break;
                    case FlagStyle.FlagEscape:
                        {
                            htmlCode = lsCode[i].Code.Remove(0, 1);
                        }
                        break;
                }
                sbHtml.Append(htmlCode);
                iPosition = lsCode[i].End + 1;
                bTemp = new char[iPosition - lsCode[i].Start];
                if (bTemp.Length != 0)
                {
                    _stringReader.Read(bTemp, 0, bTemp.Length);
                }
                if ((i + 1) != lsCode.Count) continue;
                bTemp = new char[1024];
                int iLength;
                do
                {
                    iLength = _stringReader.Read(bTemp, 0, bTemp.Length);
                    sbHtml.Append(bTemp, 0, iLength);
                } while (iLength == 1024);
            }
        }




        /// <summary>
        /// 关闭资源
        /// </summary>
        private void Dispose()
        {
            if (_stringReader != null)
            {
                _stringReader.Close();
            }
        }
    }
}
